package org.fxcontainer.registry
{
	import com.developmentarc.core.datastructures.utils.HashTable;
	
	import org.as3commons.logging.ILogger;
	import org.as3commons.logging.LoggerFactory;
	import org.fxcontainer.controls.IControl;
	import org.fxcontainer.structure.IPage;
	
	/**
	 * Represents <code>IControl</code> registry.<br/>
	 * Holds/registers controls per page to allow simple way to control invocation. 
	 * @author Izzet_Mustafayev
	 */
	public final class ControlRegistry
	{ 
		/**
		 * The <code>ILogger</code> instance.
		 */
		static private var logger:ILogger = LoggerFactory.getClassLogger(ControlRegistry);
		
		/**
		 * Contains controls per page registered. 
		 */
		private var controlStack:HashTable;
		
		/**
		 * Holds singleton reference to the <code>ControlRegistry</code> instance.
		 */
		static private var registry:ControlRegistry;
		
		/**
		 * The <code>ControlRegistry</code> constructor.
		 */
		public function ControlRegistry()
		{
			this.controlStack = new HashTable();
		}
		
		/**
		 * Creates singleton instance of the <code>ControlRegistry</code> if it does not exist,<br/> otherwise creates new one.
		 * @return the <code>ControlRegistry</code> instance
		 */
		static private function get instance():ControlRegistry
		{
			if (null == registry){
				logger.debug("Control registry was instantiated.");
				registry = new ControlRegistry();
			}
			return registry;
		}
		
		/**
		 * Registers <code>IControl</code> with a given <code>IPage</code>. 
		 * @param page the page to register the control with
		 * @param control the control to register with given page
		 */
		static public function register(page:IPage, control:IControl):void
		{
			instance.registerControl(page, control);
		}
		
		/**
		 * Performs the <code>IControl</code> registration with given <code>IPage</code>.
		 * @param page the page to register the control with
		 * @param control the control to register with given page
		 */
		private function registerControl(page:IPage, control:IControl):void
		{	
			//we cannot register nulls
			if (null != page || null != control){
				var pageControls:HashTable;
				var isPageControlStackExists:Boolean = controlStack.containsKey(page.pageName());
				if (isPageControlStackExists){
					pageControls = HashTable(controlStack.getItem(page.pageName()));
				}
				if(!isPageControlStackExists){					
					pageControls = new HashTable();
					controlStack.addItem(page.pageName(), pageControls);
				}
				//check whether control with this name already exists and register if this is false
				if (!pageControls.containsKey(control.controlName())){
					pageControls.addItem(control.controlName(), control);
				}
			}
		}
		
		/**
		 * Retrieves <code>IControl</code> from page controls stack by given control name. 
		 * @param pageName the page name to retrieve control from
		 * @param controlName the control name to reterieve
		 * @return the <code>IControl</code> instance or null if it does not exist
		 */
		static public function getControl(pageName:String, controlName:String):IControl
		{
			var control:IControl = null;
			if (null != pageName && null != controlName && instance.controlStack.containsKey(pageName)){
				var pageControls:HashTable = instance.controlStack.getItem(pageName) as HashTable;
				control = pageControls.getItem(controlName) as IControl;
			}
			return control;
		}			
	}
}